#ifndef QXGAME_GAMEANIMATION_H
#define QXGAME_GAMEANIMATION_H

#include <vector>
#include <functional>
#include "SDL.h"
#include "GameTimer.h"
#include "GameVector.h"

class GameAnimation {
public:
    GameAnimation()
    {
        timer.oneShot = false;
        timer.onTimeout = [&]() {
            idxFrame++;
            if (idxFrame >= rectSrcList.size()) {
                idxFrame = isLoop ? 0 : rectSrcList.size() - 1;
                if (!isLoop && onFinished) {
                    onFinished();
                }
            }
        };
    }

    ~GameAnimation() = default;

    void Copy(const GameAnimation &animation)
    {
        this->isLoop = animation.isLoop;
        this->texture = animation.texture;
        this->widthFrame = animation.widthFrame;
        this->heightFrame = animation.heightFrame;
        this->rectSrcList = animation.rectSrcList;
    }

    void Reset()
    {
        timer.Restart();
        idxFrame = 0;
    }

    void SetInterval(double interval)
    {
        timer.waitTime = interval;
    }

    void OnUpdate(double delta)
    {
        timer.OnUpdate(delta);
    }

    void OnRender(SDL_Renderer *renderer, const GameVector &pos, double angle = 0) const
    {
        if (idxFrame >= rectSrcList.size()) {
            return;
        }
        SDL_Rect rectDst;
        rectDst.x = pos.x - widthFrame / 2;
        rectDst.y = pos.y - heightFrame / 2;
        rectDst.w = widthFrame, rectDst.h = heightFrame;
        SDL_RenderCopyEx(renderer, texture, &rectSrcList[idxFrame], &rectDst,
                         angle, nullptr, SDL_RendererFlip::SDL_FLIP_NONE);
    }

    void SetFrameData(SDL_Texture *srcTexture, int hNum, int wNum, const std::vector<int> &idxList)
    {
        int widthTex, heightTex;
        this->texture = srcTexture;
        SDL_QueryTexture(srcTexture, nullptr, nullptr, &widthTex, &heightTex);
        widthFrame = widthTex / wNum, heightFrame = heightTex / hNum;
        rectSrcList.resize(idxList.size());
        for (size_t i = 0; i < idxList.size(); i++) {
            int idx = idxList[i];
            SDL_Rect &rect_src = rectSrcList[i];
            rect_src.x = (idx % wNum) * widthFrame;
            rect_src.y = (idx / wNum) * heightFrame;
            rect_src.w = widthFrame, rect_src.h = heightFrame;
        }
    }

    static void InitFrameData(SDL_Texture *srcTexture, GameAnimation animation[], int hNum, int wNum, bool loop = true,
                              const std::function<void()> &fn = nullptr, double interval = 0.1)
    {
        for (size_t i = 0; i < hNum; i++) {
            std::vector<int> idxList;
            for (size_t j = 0; j < wNum; j++) {
                idxList.emplace_back(i * wNum + j);
            }
            animation[i].SetFrameData(srcTexture, hNum, wNum, idxList);
            animation[i].isLoop = loop;
            animation[i].onFinished = fn;
            animation[i].SetInterval(interval);
        }
    }

public:
    bool isLoop = true;                     // 是否循环播放
    std::function<void()> onFinished;       // 动画结束的事件
    SDL_Texture *texture = nullptr;         // 实际动画所用的纹理
    std::vector<SDL_Rect> rectSrcList;      // 裁剪矩形的数组
    int widthFrame = 0, heightFrame = 0;    // 记录动画的宽度和高度
    GameTimer timer;

private:
    size_t idxFrame = 0;                     // 当前的桢索引
};


#endif //QXGAME_GAMEANIMATION_H
